#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<functional>
#include<unistd.h>
#include<sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"ThreadPool.hpp"
#include"LockGuard.hpp"
#include"InetAddr.hpp"


using task_t = std::function<void()>; //因为threapool里面执行人物的t()没有参数


//消息转发模块
class Route
{
private:
    
public:
    Route()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }

    void CheckOnlineUser(InetAddr& who)
    {

        LockGuard lockguard(&_mutex);
        for(auto& user : _online_user)
        {
            if(user == who)
            {
                LOG(DEBUG, "[%s] is exists\n", who.AddrStr().c_str());
                return;
            }
        }
        LOG(DEBUG, "[%s] is not exists\n", who.AddrStr().c_str());

        _online_user.push_back(who);
    }
    void Offline(InetAddr& who)
    {
        LockGuard lockguard(&_mutex);
        auto iter = _online_user.begin();
        for(; iter != _online_user.end(); iter++)
        {
            if(*iter == who)
            {
                LOG(DEBUG, "[%s] is not offline\n", who.AddrStr().c_str()); //离线
                _online_user.erase(iter);
                break;
            }
        }
    }

    void ForwardHelper(int sockfd,const std::string& message, InetAddr who)
    {
        LockGuard lockguard(&_mutex);        
        std::string send_message = "[" + who.AddrStr() + "]#" + message;
        for(auto& iter : _online_user)
        {
            LOG(DEBUG, "Forward message to %s, message is %s \n", iter.AddrStr().c_str(), message);
            struct sockaddr_in peer = iter.Addr();
            sendto(sockfd, send_message.c_str(), sizeof(send_message), 0, (struct sockaddr*)&peer, sizeof(peer));
        }
    }


    //什么消息 谁发的
    void Forward(int sockfd, const std::string& message, InetAddr& who)
    {
        //1.保证该用户是否 在在线用户列表里 如果在，什么都不做 如果不在 自动添加到 _onlieuser
        CheckOnlineUser(who);

        //1.1 quit 退出
        if(message == "QUIT" || message == "Q")
        {
            Offline(who);
        }

        //2.who 一定在用户列表里
        //ForwardHelper(sockfd, message)

        task_t t = std::bind(&Route::ForwardHelper, this, sockfd, message, who);
        ThreadPool<task_t>::GetInstance()->Equeue(t); //静态函数返回指针对象再解引用
    }
    ~Route()
    {
        pthread_mutex_destroy(&_mutex);
    }
private:
    std::vector<InetAddr> _online_user;
    pthread_mutex_t _mutex;

};

